/*!
 * 文件名称： driver_i2c.c
 * 描    述： i2c 驱动文件
 * 版本：     2023-12-03, V1.0
*/

/*
* GD32F303东方红开发板V1.0
* 淘宝商城：   https://juwo.taobao.com
* 技术交流：   https://www.gd32bbs.com/ask/
* 视频学习：   https://space.bilibili.com/475462605
* 微信公众号： gd32bbs
* Copyright    苏州聚沃电子科技有限公司
* 版权所有，盗版必究。
*/

#include "driver_i2c.h"

I2C_SCL_GPIO_DEF(BOARD_I2C,B,10,NULL);
I2C_SDA_GPIO_DEF(BOARD_I2C,B,11,NULL);
I2C_DEF(BOARD_I2C,I2C1,100000,0x60,MODE_POLL); 

/*!
* 说明     i2c stop发送（可恢复从机锁死总线）
* 输入[1]  i2cx：i2cx结构体指针 
* 返回值   无
*/
void driver_i2c_stop(typdef_i2c_struct *i2cx)
{
    __IO uint8_t i=0,delay=0;    
    uint64_t timeout = driver_tick;     
    i2c_ack_config(i2cx->i2c_x, I2C_ACK_DISABLE);
    if(i2c_flag_get(i2cx->i2c_x,I2C_FLAG_I2CBSY)){
        i2c_stop_on_bus(i2cx->i2c_x); 
        while(I2C_CTL0(i2cx->i2c_x)&0x0200){                      
            if((timeout+I2C_TIMEOUT_MS) <= driver_tick) { 
                
                GPIO_BOP(i2cx->i2c_scl_gpio->port)=i2cx->i2c_scl_gpio->pin; 
                GPIO_BOP(i2cx->i2c_sda_gpio->port)=i2cx->i2c_sda_gpio->pin; 
                
                i2cx->i2c_sda_gpio->gpio_mode=OUT_OD;
                i2cx->i2c_scl_gpio->gpio_mode=OUT_OD;

                driver_gpio_general_init(i2cx->i2c_scl_gpio);                
                driver_gpio_general_init(i2cx->i2c_sda_gpio);

                for(i=0;i<9;i++)
                {
                    GPIO_BC(i2cx->i2c_scl_gpio->port)=i2cx->i2c_scl_gpio->pin; 
                    delay_us(1000000/i2cx->frequency/2);
                    GPIO_BOP(i2cx->i2c_scl_gpio->port)=i2cx->i2c_scl_gpio->pin; 
                    delay_us(1000000/i2cx->frequency/2);
                }
                
                i2cx->i2c_sda_gpio->gpio_mode=AF_OD;
                i2cx->i2c_scl_gpio->gpio_mode=AF_OD;                
                driver_i2c_init(i2cx);              
            }               
        }
    }
    i2c_ack_config(i2cx->i2c_x, I2C_ACK_ENABLE);
    i2c_ackpos_config(i2cx->i2c_x,I2C_ACKPOS_CURRENT);
}

/*!
* 说明     超时等待flag状态
* 输入[1]  i2cx：i2cx结构体指针
* 输入[2]  flag：等待的flag
* 输入[3]  wait_state：等待的flag状态 
* 返回值   无
*/
Drv_Err driver_i2c_flag_wait_timeout(typdef_i2c_struct *i2cx, i2c_flag_enum flag ,FlagStatus wait_state)
{
    uint64_t timeout = driver_tick;    
    while(wait_state!=i2c_flag_get(i2cx->i2c_x, flag)){
        if((timeout+I2C_TIMEOUT_MS) <= driver_tick) {              
            return DRV_ERROR;
        } 
    }
    return DRV_SUCCESS;
}


/*
*说明 :主I2C向从I2C地址器件写N字节数据
*输入[1]              i2cx：i2cx结构体指针
*输入[2]               i2c_slave_addr --- I2C地址7位
 输入[3]               slave_reg_addr --- 目标寄存器地址
 输入[4]               reg_addr_type  --- 目标寄存器地址宽度 MEM_ADDRESS_8BIT/MEM_ADDRESS_16BIT 
 输入[5]               *pbuff --- 写数据缓存   
 输入[6]               Length--- 写数据长度   
 输入[7]     
*返回值                i2c_state --- I2C通信是否成功
*/
Drv_Err driver_i2c_mem_poll_write(typdef_i2c_struct *i2cx,uint8_t i2c_slave_addr,uint16_t slave_reg_addr,i2c_mem_type_enum reg_addr_type,uint8_t *pbuff,uint16_t Length)
{
    Drv_Err i2c_state=DRV_SUCCESS;
    
    i2cx->i2c_control.Com_Flag.Bits.SendSucess=0;
    i2cx->i2c_control.Com_Flag.Bits.SendState=1;    
    i2cx->i2c_control.p_Send=pbuff;
    i2cx->i2c_control.SendSize=Length; 
    i2cx->i2c_control.SendCount=0;    
    
    /* wait until I2C bus is idle */  
    i2c_state=driver_i2c_flag_wait_timeout(i2cx, I2C_FLAG_I2CBSY,RESET);
    if(i2c_state!=DRV_SUCCESS){
        driver_i2c_stop(i2cx);
        return DRV_ERROR;
    }
    
    /* send a start condition to I2C bus */
    i2c_start_on_bus(i2cx->i2c_x);
    /* wait until SBSEND bit is set */
    i2c_state=driver_i2c_flag_wait_timeout(i2cx, I2C_FLAG_SBSEND,SET);
    if(i2c_state!=DRV_SUCCESS){
        driver_i2c_stop(i2cx);
        return DRV_ERROR;
    }

    /* send slave address to I2C bus */
    i2c_master_addressing(i2cx->i2c_x, i2c_slave_addr, I2C_TRANSMITTER);
    /* wait until ADDSEND bit is set */
    i2c_state=driver_i2c_flag_wait_timeout(i2cx, I2C_FLAG_ADDSEND,SET);
    if(i2c_state!=DRV_SUCCESS){
        driver_i2c_stop(i2cx);
        return DRV_ERROR;       
    }
    
    /* clear ADDSEND bit */
    i2c_flag_clear(i2cx->i2c_x, I2C_FLAG_ADDSEND);
    
    if(Length==0)
    {
        driver_i2c_stop(i2cx);
        i2cx->i2c_control.Com_Flag.Bits.SendSucess=1;
        i2cx->i2c_control.Com_Flag.Bits.SendState=0; 
    
        return DRV_SUCCESS;        
    }
    
    /* wait until the transmit data buffer is empty */
    i2c_state=driver_i2c_flag_wait_timeout(i2cx, I2C_FLAG_TBE,SET);
    if(i2c_state!=DRV_SUCCESS){
        driver_i2c_stop(i2cx);
        return DRV_ERROR;
    }    

    if(reg_addr_type==MEM_ADDRESS_16BIT)
    {
        i2c_data_transmit(i2cx->i2c_x, (uint8_t)((slave_reg_addr>>8)&0x00ff));
        /* wait until BTC bit is set */
        i2c_state=driver_i2c_flag_wait_timeout(i2cx, I2C_FLAG_TBE,SET);
        if(i2c_state!=DRV_SUCCESS){
            driver_i2c_stop(i2cx);
            return DRV_ERROR;
        }        
    }

    /* send the EEPROM's internal address to write to : only one byte address */
    i2c_data_transmit(i2cx->i2c_x, (uint8_t)(slave_reg_addr&0x00ff));
   
    /* wait until BTC bit is set */
    i2c_state=driver_i2c_flag_wait_timeout(i2cx, I2C_FLAG_BTC,SET);
    if(i2c_state!=DRV_SUCCESS){
        driver_i2c_stop(i2cx);
        return DRV_ERROR;
    }
    
    while(Length){
        /* data transmission */
        i2c_data_transmit(i2cx->i2c_x, pbuff[i2cx->i2c_control.SendCount]);        
        /* point to the next byte to be written */
        i2cx->i2c_control.SendCount++;
        Length--;
        /* wait until the TBE bit is set */
        i2c_state=driver_i2c_flag_wait_timeout(i2cx, I2C_FLAG_TBE,SET);
        if(i2c_state!=DRV_SUCCESS){
            driver_i2c_stop(i2cx);
            return DRV_ERROR;
        }
    }
    
    driver_i2c_stop(i2cx);
    i2cx->i2c_control.Com_Flag.Bits.SendSucess=1;
    i2cx->i2c_control.Com_Flag.Bits.SendState=0; 
    
	return DRV_SUCCESS;
}
                
__IO uint8_t test=0xa5;
/*
*说明 :主I2C向从I2C地址器件读N字节数据
*输入[1]              i2cx：i2cx结构体指针
*输入[2]               i2c_slave_addr --- I2C地址7位
 输入[3]               slave_reg_addr --- 目标寄存器地址
 输入[4]               reg_addr_type  --- 目标寄存器地址宽度 MEM_ADDRESS_8BIT/MEM_ADDRESS_16BIT 
 输入[5]               *pbuff --- 数据缓存   
 输入[6]               Length--- 数据长度   
 输入[7]     
*返回值                i2c_state --- I2C通信是否成功
*/
Drv_Err driver_i2c_mem_poll_read(typdef_i2c_struct *i2cx,uint8_t i2c_slave_addr,uint16_t slave_reg_addr,i2c_mem_type_enum reg_addr_type,uint8_t *pbuff,uint16_t Length)
{
    Drv_Err i2c_state=DRV_SUCCESS;
    
    i2cx->i2c_control.Com_Flag.Bits.RecSuccess=0;
    i2cx->i2c_control.Com_Flag.Bits.RecState=1;    
    i2cx->i2c_control.p_Rec=pbuff;
    i2cx->i2c_control.RecSize=Length; 
    i2cx->i2c_control.RecCount=0;   
    
    /* wait until I2C bus is idle */  
    i2c_state=driver_i2c_flag_wait_timeout(i2cx, I2C_FLAG_I2CBSY,RESET);
    if(i2c_state!=DRV_SUCCESS){
        driver_i2c_stop(i2cx);
        return DRV_ERROR;
    }

    if(2 == Length){
        i2c_ackpos_config(i2cx->i2c_x,I2C_ACKPOS_NEXT);
    }
    
    /* send a start condition to I2C bus */
    i2c_start_on_bus(i2cx->i2c_x);
    
    /* wait until SBSEND bit is set */
    i2c_state=driver_i2c_flag_wait_timeout(i2cx, I2C_FLAG_SBSEND,SET);
    if(i2c_state!=DRV_SUCCESS){
        driver_i2c_stop(i2cx);
        return DRV_ERROR;
    }
    
    /* send slave address to I2C bus */
    i2c_master_addressing(i2cx->i2c_x, i2c_slave_addr, I2C_TRANSMITTER);
    
    i2c_state=driver_i2c_flag_wait_timeout(i2cx, I2C_FLAG_ADDSEND,SET);
    if(i2c_state!=DRV_SUCCESS){
        driver_i2c_stop(i2cx);
        return DRV_ERROR;
    }
    
    /* clear the ADDSEND bit */
    i2c_flag_clear(i2cx->i2c_x,I2C_FLAG_ADDSEND);
    
    /* wait until the transmit data buffer is empty */
    i2c_state=driver_i2c_flag_wait_timeout(i2cx, I2C_FLAG_TBE,SET);
    if(i2c_state!=DRV_SUCCESS){
        driver_i2c_stop(i2cx);
        return DRV_ERROR;
    }

    /* enable i2cx->i2c_x*/
    i2c_enable(i2cx->i2c_x);
    
    /* send the EEPROM's internal address to write to */
    if(reg_addr_type==MEM_ADDRESS_16BIT)
    {
        i2c_data_transmit(i2cx->i2c_x, (uint8_t)((slave_reg_addr>>8)&0x00ff));
        /* wait until BTC bit is set */
        i2c_state=driver_i2c_flag_wait_timeout(i2cx, I2C_FLAG_TBE,SET);
        if(i2c_state!=DRV_SUCCESS){
            driver_i2c_stop(i2cx);
            return DRV_ERROR;
        }        
    }

    /* send the EEPROM's internal address to write to : only one byte address */
    i2c_data_transmit(i2cx->i2c_x, (uint8_t)(slave_reg_addr&0x00ff));
    
    /* wait until BTC bit is set */
    i2c_state=driver_i2c_flag_wait_timeout(i2cx, I2C_FLAG_BTC,SET);
    if(i2c_state!=DRV_SUCCESS){
        driver_i2c_stop(i2cx);
        return DRV_ERROR;
    }
    
    /* send a start condition to I2C bus */
    i2c_start_on_bus(i2cx->i2c_x);
    
    /* wait until SBSEND bit is set */
    i2c_state=driver_i2c_flag_wait_timeout(i2cx, I2C_FLAG_SBSEND,SET);
    if(i2c_state!=DRV_SUCCESS){
        driver_i2c_stop(i2cx);
        return DRV_ERROR;
    }
    
    /* send slave address to I2C bus */
    i2c_master_addressing(i2cx->i2c_x, i2c_slave_addr, I2C_RECEIVER);

    if(Length < 3){
        /* disable acknowledge */
        i2c_ack_config(i2cx->i2c_x,I2C_ACK_DISABLE);
    }
    
    /* wait until ADDSEND bit is set */
    i2c_state=driver_i2c_flag_wait_timeout(i2cx, I2C_FLAG_ADDSEND,SET);
    if(i2c_state!=DRV_SUCCESS){
        driver_i2c_stop(i2cx);
        return DRV_ERROR;
    }    
    /* clear the ADDSEND bit */
    i2c_flag_clear(i2cx->i2c_x,I2C_FLAG_ADDSEND);
    
    if(1 == Length){
        /* send a stop condition to I2C bus */
        i2c_stop_on_bus(i2cx->i2c_x);
    }
    
    /* while there is data to be read */
    while(Length){
        if(3 == Length){
            /* wait until BTC bit is set */
            i2c_state=driver_i2c_flag_wait_timeout(i2cx, I2C_FLAG_BTC,SET);
            if(i2c_state!=DRV_SUCCESS){
                driver_i2c_stop(i2cx);
                return DRV_ERROR;
            }
            /* disable acknowledge */
            i2c_ack_config(i2cx->i2c_x,I2C_ACK_DISABLE);

            __disable_irq();            
            I2C_STAT0(i2cx->i2c_x);
            /* read a byte from the EEPROM */
            *pbuff = i2c_data_receive(i2cx->i2c_x);
            __enable_irq();             
            /* point to the next location where the byte read will be saved */
            pbuff++;         
            /* decrement the read bytes counter */
            Length--;            

            /* wait until BTC bit is set */
            i2c_state=driver_i2c_flag_wait_timeout(i2cx, I2C_FLAG_BTC,SET);
            if(i2c_state!=DRV_SUCCESS){
                driver_i2c_stop(i2cx);
                return DRV_ERROR;
            }
            
            __disable_irq();            
            i2c_stop_on_bus(i2cx->i2c_x);              
            /* send a stop condition to I2C bus */
            I2C_STAT0(i2cx->i2c_x);
            /* read a byte from the EEPROM */
            *pbuff = i2c_data_receive(i2cx->i2c_x);
            /* point to the next location where the byte read will be saved */
            pbuff++;         
            /* decrement the read bytes counter */
            Length--;            
            /* read a byte from the EEPROM */
            *pbuff = i2c_data_receive(i2cx->i2c_x);                                 
            __enable_irq();   
            /* point to the next location where the byte read will be saved */
            pbuff++;         
            /* decrement the read bytes counter */
            Length--;    
        }
        if(2 == Length){
            /* wait until BTC bit is set */
            i2c_state=driver_i2c_flag_wait_timeout(i2cx, I2C_FLAG_BTC,SET);
            if(i2c_state!=DRV_SUCCESS){
                driver_i2c_stop(i2cx);
                return DRV_ERROR;
            } 
            /* disable acknowledge */
            i2c_ack_config(i2cx->i2c_x,I2C_ACK_DISABLE); 
            
            __disable_irq();             
            i2c_stop_on_bus(i2cx->i2c_x);            
            /* send a stop condition to I2C bus */
            I2C_STAT0(i2cx->i2c_x);
            /* read a byte from the EEPROM */
            *pbuff = i2c_data_receive(i2cx->i2c_x);
            /* point to the next location where the byte read will be saved */
            pbuff++;         
            /* decrement the read bytes counter */
            Length--;
            
            /* read a byte from the EEPROM */
            *pbuff = i2c_data_receive(i2cx->i2c_x);
            __enable_irq();              
            /* point to the next location where the byte read will be saved */
            pbuff++;         
            /* decrement the read bytes counter */
            Length--;                         

        }
        
        if(Length>3){
            /* wait until the RBNE bit is set and clear it */
            i2c_state=driver_i2c_flag_wait_timeout(i2cx, I2C_FLAG_BTC,SET);
            if(i2c_state!=DRV_SUCCESS){
                driver_i2c_stop(i2cx);
                return DRV_ERROR;
            }
            
            __disable_irq();
            
            I2C_STAT0(i2cx->i2c_x);
            /* read a byte from the EEPROM */
            *pbuff = i2c_data_receive(i2cx->i2c_x);
            /* point to the next location where the byte read will be saved */
            pbuff++;         
            /* decrement the read bytes counter */
            Length--;            
            /* read a byte from the EEPROM */
            *pbuff = i2c_data_receive(i2cx->i2c_x);            
            __enable_irq();
            /* point to the next location where the byte read will be saved */
            pbuff++;         
            /* decrement the read bytes counter */
            Length--;             
        }
        else if(Length!=0)
        {
            /* wait until the RBNE bit is set and clear it */
            i2c_state=driver_i2c_flag_wait_timeout(i2cx, I2C_FLAG_RBNE,SET);
            if(i2c_state!=DRV_SUCCESS){
                driver_i2c_stop(i2cx);
                return DRV_ERROR;
            }
            __disable_irq();            
            I2C_STAT0(i2cx->i2c_x);
            /* read a byte from the EEPROM */
            *pbuff = i2c_data_receive(i2cx->i2c_x);
            __enable_irq();
            /* point to the next location where the byte read will be saved */
            pbuff++;         
            /* decrement the read bytes counter */
            Length--;            
        }                  
    }
        
    driver_i2c_stop(i2cx);
    
    i2cx->i2c_control.Com_Flag.Bits.RecSuccess=1;
    i2cx->i2c_control.Com_Flag.Bits.RecState=0;    

    return DRV_SUCCESS ;
}

/*
*说明 :主I2C读N字节数据
*输入[1]              i2cx：i2cx结构体指针
*输入[2]               i2c_slave_addr --- I2C地址7位
 输入[3]               reg_addr_type  --- 目标寄存器地址宽度 MEM_ADDRESS_8BIT/MEM_ADDRESS_16BIT 
 输入[4]               *pbuff --- 数据缓存   
 输入[5]               Length--- 数据长度   
 输入[6]     
*返回值                i2c_state --- I2C通信是否成功
*/
Drv_Err driver_i2c_poll_read(typdef_i2c_struct *i2cx,uint8_t i2c_slave_addr,uint8_t *pbuff,uint16_t Length)
{
    Drv_Err i2c_state=DRV_SUCCESS;
    
    i2cx->i2c_control.Com_Flag.Bits.RecSuccess=0;
    i2cx->i2c_control.Com_Flag.Bits.RecState=1;     
    i2cx->i2c_control.p_Rec=pbuff;
    i2cx->i2c_control.RecSize=Length; 
    i2cx->i2c_control.RecCount=0;   
    
    /* wait until I2C bus is idle */  
    i2c_state=driver_i2c_flag_wait_timeout(i2cx, I2C_FLAG_I2CBSY,RESET);
    if(i2c_state!=DRV_SUCCESS){
        driver_i2c_stop(i2cx);
        return DRV_ERROR;
    }

    if(2 == Length){
        i2c_ackpos_config(i2cx->i2c_x,I2C_ACKPOS_NEXT);
    }
    
    /* send a start condition to I2C bus */
    i2c_start_on_bus(i2cx->i2c_x);
    
    /* wait until SBSEND bit is set */
    i2c_state=driver_i2c_flag_wait_timeout(i2cx, I2C_FLAG_SBSEND,SET);
    if(i2c_state!=DRV_SUCCESS){
        driver_i2c_stop(i2cx);
        return DRV_ERROR;
    }
    
    /* send slave address to I2C bus */
    i2c_master_addressing(i2cx->i2c_x, i2c_slave_addr, I2C_RECEIVER);

    if(Length < 3){
        /* disable acknowledge */
        i2c_ack_config(i2cx->i2c_x,I2C_ACK_DISABLE);
    }
    
    /* wait until ADDSEND bit is set */
    i2c_state=driver_i2c_flag_wait_timeout(i2cx, I2C_FLAG_ADDSEND,SET);
    if(i2c_state!=DRV_SUCCESS){
        driver_i2c_stop(i2cx);
        return DRV_ERROR;
    }    
    /* clear the ADDSEND bit */
    i2c_flag_clear(i2cx->i2c_x,I2C_FLAG_ADDSEND);
    
    if(1 == Length){
        /* send a stop condition to I2C bus */
        i2c_stop_on_bus(i2cx->i2c_x);
    }
    
    /* while there is data to be read */
    while(Length){
        if(3 == Length){
            /* wait until BTC bit is set */
            i2c_state=driver_i2c_flag_wait_timeout(i2cx, I2C_FLAG_BTC,SET);
            if(i2c_state!=DRV_SUCCESS){
                driver_i2c_stop(i2cx);
                return DRV_ERROR;
            }
            /* disable acknowledge */
            i2c_ack_config(i2cx->i2c_x,I2C_ACK_DISABLE);
        }
        if(2 == Length){
            /* wait until BTC bit is set */
            i2c_state=driver_i2c_flag_wait_timeout(i2cx, I2C_FLAG_BTC,SET);
            if(i2c_state!=DRV_SUCCESS){
                driver_i2c_stop(i2cx);
                return DRV_ERROR;
            }                
            /* send a stop condition to I2C bus */
            i2c_stop_on_bus(i2cx->i2c_x);
        }
        
        /* wait until the RBNE bit is set and clear it */
        i2c_state=driver_i2c_flag_wait_timeout(i2cx, I2C_FLAG_RBNE,SET);
        if(i2c_state!=DRV_SUCCESS){
            driver_i2c_stop(i2cx);
            return DRV_ERROR;
        }
        /* read a byte from the EEPROM */
        *pbuff = i2c_data_receive(i2cx->i2c_x);
        
        /* point to the next location where the byte read will be saved */
        pbuff++; 
        
        /* decrement the read bytes counter */
        Length--;
    }
        
    driver_i2c_stop(i2cx);
    
    i2cx->i2c_control.Com_Flag.Bits.RecSuccess=1;
    i2cx->i2c_control.Com_Flag.Bits.RecState=0;    

    return DRV_SUCCESS ;
}

/*
*说明 :主I2C写N字节数据
*输入[1]              i2cx：i2cx结构体指针
*输入[2]               i2c_slave_addr --- I2C地址7位
 输入[3]               reg_addr_type  --- 目标寄存器地址宽度 MEM_ADDRESS_8BIT/MEM_ADDRESS_16BIT 
 输入[4]               *pbuff --- 数据缓存   
 输入[5]               Length--- 数据长度   
 输入[6]     
*返回值                i2c_state --- I2C通信是否成功
*/
Drv_Err driver_i2c_poll_write(typdef_i2c_struct *i2cx,uint8_t i2c_slave_addr,uint8_t *pbuff,uint16_t Length)
{
    Drv_Err i2c_state=DRV_SUCCESS;
    
    i2cx->i2c_control.Com_Flag.Bits.SendSucess=0;
    i2cx->i2c_control.Com_Flag.Bits.SendState=1;    
    i2cx->i2c_control.p_Send=pbuff;
    i2cx->i2c_control.SendSize=Length; 
    i2cx->i2c_control.SendCount=0;    
    
    /* wait until I2C bus is idle */  
    i2c_state=driver_i2c_flag_wait_timeout(i2cx, I2C_FLAG_I2CBSY,RESET);
    if(i2c_state!=DRV_SUCCESS){
        driver_i2c_stop(i2cx);
        return DRV_ERROR;
    }
    
    /* send a start condition to I2C bus */
    i2c_start_on_bus(i2cx->i2c_x);
    /* wait until SBSEND bit is set */
    i2c_state=driver_i2c_flag_wait_timeout(i2cx, I2C_FLAG_SBSEND,SET);
    if(i2c_state!=DRV_SUCCESS){
        driver_i2c_stop(i2cx);
        return DRV_ERROR;
    }

    /* send slave address to I2C bus */
    i2c_master_addressing(i2cx->i2c_x, i2c_slave_addr, I2C_TRANSMITTER);
    /* wait until ADDSEND bit is set */
    i2c_state=driver_i2c_flag_wait_timeout(i2cx, I2C_FLAG_ADDSEND,SET);
    if(i2c_state!=DRV_SUCCESS){
        driver_i2c_stop(i2cx);
        return DRV_ERROR;       
    }
    
    /* clear ADDSEND bit */
    i2c_flag_clear(i2cx->i2c_x, I2C_FLAG_ADDSEND);
         
    while(Length--){

        /* wait until the TBE bit is set */
        i2c_state=driver_i2c_flag_wait_timeout(i2cx, I2C_FLAG_TBE,SET);
        if(i2c_state!=DRV_SUCCESS){
            driver_i2c_stop(i2cx);
            return DRV_ERROR;
        }
        
        /* data transmission */
        i2c_data_transmit(i2cx->i2c_x, pbuff[i2cx->i2c_control.SendCount]);
        
        /* point to the next byte to be written */
        i2cx->i2c_control.SendCount++;       
    }
    
    /* wait until BTC bit is set */
    i2c_state=driver_i2c_flag_wait_timeout(i2cx, I2C_FLAG_BTC,SET);
    if(i2c_state!=DRV_SUCCESS){
        driver_i2c_stop(i2cx);
        return DRV_ERROR;
    }
    
    driver_i2c_stop(i2cx);
    i2cx->i2c_control.Com_Flag.Bits.SendSucess=1;
    i2cx->i2c_control.Com_Flag.Bits.SendState=0; 
    
	return DRV_SUCCESS;
}

/*
*说明 :主I2C读一个字节数据
*输入[1]              i2cx：i2cx结构体指针
*输入[2]               i2c_slave_addr --- I2C地址7位    
*返回值                数据
*/
uint8_t driver_i2c_master_read_byte(typdef_i2c_struct *i2cx,uint8_t i2c_slave_addr)
{
    Drv_Err i2c_state;
    
    i2cx->i2c_control.Com_Flag.Bits.RecSuccess=0;
    i2cx->i2c_control.Com_Flag.Bits.RecState=1; 
    
    uint8_t Data=0;    
    /* wait until I2C bus is idle */  
    i2c_state=driver_i2c_flag_wait_timeout(i2cx, I2C_FLAG_I2CBSY,RESET);
    if(i2c_state!=DRV_SUCCESS){
        driver_i2c_stop(i2cx);
    }
    
    /* send a start condition to I2C bus */
    i2c_start_on_bus(i2cx->i2c_x);
    
    /* wait until SBSEND bit is set */
    i2c_state=driver_i2c_flag_wait_timeout(i2cx, I2C_FLAG_SBSEND,SET);
    if(i2c_state!=DRV_SUCCESS){
        driver_i2c_stop(i2cx);
    }
    
    /* send slave address to I2C bus */
    i2c_master_addressing(i2cx->i2c_x, i2c_slave_addr, I2C_RECEIVER);

    /* disable acknowledge */
    i2c_ack_config(i2cx->i2c_x,I2C_ACK_DISABLE);
    
    /* wait until ADDSEND bit is set */
    i2c_state=driver_i2c_flag_wait_timeout(i2cx, I2C_FLAG_ADDSEND,SET);
    if(i2c_state!=DRV_SUCCESS){
        driver_i2c_stop(i2cx);
    }    
    /* clear the ADDSEND bit */
    i2c_flag_clear(i2cx->i2c_x,I2C_FLAG_ADDSEND);
    
    i2c_stop_on_bus(i2cx->i2c_x);
    
        
    /* wait until the RBNE bit is set and clear it */
    i2c_state=driver_i2c_flag_wait_timeout(i2cx, I2C_FLAG_RBNE,SET);
    if(i2c_state!=DRV_SUCCESS){
        driver_i2c_stop(i2cx);
    }
    /* read a byte from the EEPROM */
    Data = i2c_data_receive(i2cx->i2c_x);
    
    driver_i2c_stop(i2cx);
    
    if(i2c_state==DRV_SUCCESS){
        i2cx->i2c_control.Com_Flag.Bits.RecSuccess=1;
    }
    i2cx->i2c_control.Com_Flag.Bits.RecState=0;     

    return Data ;
}

/*
*说明 :主I2C写一个字节数据
*输入[1]              i2cx：i2cx结构体指针
*输入[2]               i2c_slave_addr --- I2C地址7位
*输入[2]               data --- 数据     
*返回值                i2c_state --- I2C通信是否成功
*/
Drv_Err driver_i2c_master_write_byte(typdef_i2c_struct *i2cx,uint8_t i2c_slave_addr,uint8_t Data)
{
    Drv_Err i2c_state;
    
    /* wait until I2C bus is idle */  
    i2c_state=driver_i2c_flag_wait_timeout(i2cx, I2C_FLAG_I2CBSY,RESET);
    if(i2c_state!=DRV_SUCCESS){
        driver_i2c_stop(i2cx);
        return DRV_ERROR;
    }
    
    /* send a start condition to I2C bus */
    i2c_start_on_bus(i2cx->i2c_x);
    /* wait until SBSEND bit is set */
    i2c_state=driver_i2c_flag_wait_timeout(i2cx, I2C_FLAG_SBSEND,SET);
    if(i2c_state!=DRV_SUCCESS){
        driver_i2c_stop(i2cx);
        return DRV_ERROR;
    }

    /* send slave address to I2C bus */
    i2c_master_addressing(i2cx->i2c_x, i2c_slave_addr, I2C_TRANSMITTER);
    /* wait until ADDSEND bit is set */
    i2c_state=driver_i2c_flag_wait_timeout(i2cx, I2C_FLAG_ADDSEND,SET);
    if(i2c_state!=DRV_SUCCESS){
        driver_i2c_stop(i2cx);
        return DRV_ERROR;       
    }
    
    /* clear ADDSEND bit */
    i2c_flag_clear(i2cx->i2c_x, I2C_FLAG_ADDSEND);
    
    /* wait until the transmit data buffer is empty */
    i2c_state=driver_i2c_flag_wait_timeout(i2cx, I2C_FLAG_TBE,SET);
    if(i2c_state!=DRV_SUCCESS){
        driver_i2c_stop(i2cx);
        return DRV_ERROR;
    }    

    /* send the EEPROM's internal address to write to : only one byte address */
    i2c_data_transmit(i2cx->i2c_x, (uint8_t)Data);
   
    /* wait until BTC bit is set */
    i2c_state=driver_i2c_flag_wait_timeout(i2cx, I2C_FLAG_BTC,SET);
    if(i2c_state!=DRV_SUCCESS){
        driver_i2c_stop(i2cx);
        return DRV_ERROR;
    }
        
    driver_i2c_stop(i2cx);     
    return DRV_SUCCESS ;
}


/*
*说明 :i2c初始化
*输入[1]              i2cx：i2cx结构体指针    
*返回值               无
*/
void driver_i2c_init(typdef_i2c_struct *i2cx)
{
    rcu_periph_clock_enable(i2cx->rcu_i2c_x);

    i2c_deinit(i2cx->i2c_x);
    
    driver_gpio_general_init(i2cx->i2c_scl_gpio);
    driver_gpio_general_init(i2cx->i2c_sda_gpio);	
    
    /* I2C clock configure */
    i2c_clock_config(i2cx->i2c_x, i2cx->frequency, I2C_DTCY_2);
    /* I2C address configure */
    i2c_mode_addr_config(i2cx->i2c_x, I2C_I2CMODE_ENABLE, I2C_ADDFORMAT_7BITS, i2cx->slave_addr);
    /* enable I2C0 */
    i2c_enable(i2cx->i2c_x);
    /* enable acknowledge */
    i2c_ack_config(i2cx->i2c_x, I2C_ACK_ENABLE);    
}


//I2C相关中断
/*
*说明 :i2c事件和buff中断处理流程函数，在i2c中断里调用
*输入[1]              i2cx：i2cx结构体指针    
*返回值               无
*/
void driver_i2c_slave_int_handler(typdef_i2c_struct *i2cx)
{
    uint8_t temp=0;
    if(i2c_interrupt_flag_get(i2cx->i2c_x, I2C_INT_FLAG_ADDSEND)) 
    {
        i2cx->i2c_control.Com_Flag.Bits.Dir=i2c_flag_get(i2cx->i2c_x,I2C_FLAG_TRS);
        if(i2cx->i2c_control.Com_Flag.Bits.Dir==RESET)
        {
            i2cx->i2c_control.Com_Flag.Bits.RecState=1;
            i2cx->i2c_control.Com_Flag.Bits.RecSuccess=0;
            i2cx->i2c_control.Com_Flag.Bits.SendState=0;
            i2cx->i2c_control.Com_Flag.Bits.SendSucess=0;
            i2cx->i2c_control.RecCount=0;           
        }
        else
        {
            i2cx->i2c_control.Com_Flag.Bits.RecState=0;
            i2cx->i2c_control.Com_Flag.Bits.RecSuccess=0;
            i2cx->i2c_control.Com_Flag.Bits.SendState=1;
            i2cx->i2c_control.Com_Flag.Bits.SendSucess=0;           
            i2cx->i2c_control.SendCount=0;
        }
        if(i2cx->i2c_slave_addr_callback!=NULL){
            i2cx->i2c_slave_addr_callback(i2cx);        
        }
        /* clear the ADDSEND bit */
        i2c_interrupt_flag_clear(i2cx->i2c_x, I2C_INT_FLAG_ADDSEND);
    } 
   
    
    if(i2cx->i2c_control.Com_Flag.Bits.Dir==RESET)//接收
    {
        if((i2c_interrupt_flag_get(i2cx->i2c_x, I2C_INT_FLAG_RBNE)!=RESET)||(i2c_interrupt_flag_get(i2cx->i2c_x, I2C_INT_FLAG_BTC)!=RESET)){
            
            I2C_STAT0(i2cx->i2c_x);
            temp = i2c_data_receive(i2cx->i2c_x);            
            if(i2cx->i2c_control.RecCount < i2cx->i2c_control.RecSize)
            {              
                /* if reception data register is not empty, I2C1 will read a data from I2C_RDATA */
                i2cx->i2c_control.p_Rec[i2cx->i2c_control.RecCount] = temp;                
                i2cx->i2c_control.RecCount++;
            }
        }
    }
    else  if(i2cx->i2c_control.Com_Flag.Bits.Dir==SET)//发送
    {
        if((i2c_interrupt_flag_get(i2cx->i2c_x, I2C_INT_FLAG_TBE)) && (!i2c_interrupt_flag_get(i2cx->i2c_x, I2C_INT_FLAG_AERR))){
            /* send a data byte */
            if(i2cx->i2c_control.SendCount < i2cx->i2c_control.SendSize)
            {
                /* if reception data register is not empty, I2C1 will read a data from I2C_RDATA */
                i2c_data_transmit(i2cx->i2c_x,i2cx->i2c_control.p_Send[i2cx->i2c_control.SendCount]);
                i2cx->i2c_control.SendCount++;
            }
            else
            {
                i2c_data_transmit(i2cx->i2c_x,0xff);        
            }
        }   
    }    
    else if(i2c_interrupt_flag_get(i2cx->i2c_x, I2C_INT_FLAG_STPDET)) 
    {
        /* clear STPDET interrupt flag */
        i2c_interrupt_flag_clear(i2cx->i2c_x, I2C_INT_FLAG_STPDET);
        
        if(i2cx->i2c_control.Com_Flag.Bits.Dir==RESET)
        {
            i2cx->i2c_control.Com_Flag.Bits.SendSucess = DRV_SUCCESS;
            i2cx->i2c_control.Com_Flag.Bits.RecState = 0;
        }
        else
        {
            i2cx->i2c_control.Com_Flag.Bits.SendSucess = DRV_SUCCESS;
            i2cx->i2c_control.Com_Flag.Bits.SendState = 0;  
        }
        
        if(i2cx->i2c_slave_end_callback!=NULL){
            i2cx->i2c_slave_end_callback(i2cx);        
        }                
    }   
}

/*
*说明 :i2c错误中断处理流程函数，在i2c中断里调用
*输入[1]              i2cx：i2cx结构体指针    
*返回值               无
*/
void driver_i2c_err_int_handler(typdef_i2c_struct *i2cx)
{
    /* SMBus alert */
    if(i2c_interrupt_flag_get(i2cx->i2c_x, I2C_INT_FLAG_SMBALT)){
        i2c_interrupt_flag_clear(i2cx->i2c_x, I2C_INT_FLAG_SMBALT);
        if(i2cx->i2c_err_callback!=NULL)
        {
            i2cx->i2c_err_callback(i2cx);        
        }        
    }

    /* bus timeout in SMBus mode */
    if(i2c_interrupt_flag_get(i2cx->i2c_x, I2C_INT_FLAG_SMBTO)){
        i2c_interrupt_flag_clear(i2cx->i2c_x, I2C_INT_FLAG_SMBTO);
        if(i2cx->i2c_err_callback!=NULL)
        {
            i2cx->i2c_err_callback(i2cx);        
        }        
    }

    /* over-run or under-run when SCL stretch is disabled */
    if(i2c_interrupt_flag_get(i2cx->i2c_x, I2C_INT_FLAG_OUERR)){
       i2c_interrupt_flag_clear(i2cx->i2c_x, I2C_INT_FLAG_OUERR);
        if(i2cx->i2c_err_callback!=NULL)
        {
            i2cx->i2c_err_callback(i2cx);        
        }            
    }

    /* arbitration lost */
    if(i2c_interrupt_flag_get(i2cx->i2c_x, I2C_INT_FLAG_LOSTARB)){
        i2c_interrupt_flag_clear(i2cx->i2c_x, I2C_INT_FLAG_LOSTARB);
        if(i2cx->i2c_err_callback!=NULL)
        {
            i2cx->i2c_err_callback(i2cx);        
        }        
    }

    /* bus DRV_ERROR */
    if(i2c_interrupt_flag_get(i2cx->i2c_x, I2C_INT_FLAG_BERR)){
        i2c_interrupt_flag_clear(i2cx->i2c_x, I2C_INT_FLAG_BERR);
        if(i2cx->i2c_err_callback!=NULL)
        {
            i2cx->i2c_err_callback(i2cx);        
        }        
    }

    /* CRC value doesn't match */
    if(i2c_interrupt_flag_get(i2cx->i2c_x, I2C_INT_FLAG_PECERR)){
        i2c_interrupt_flag_clear(i2cx->i2c_x, I2C_INT_FLAG_PECERR);
        if(i2cx->i2c_err_callback!=NULL)
        {
            i2cx->i2c_err_callback(i2cx);        
        }        
    } 
    
    /* no acknowledge received */
    if(i2c_interrupt_flag_get(i2cx->i2c_x, I2C_INT_FLAG_AERR))
    {
        /* clear STPDET interrupt flag */
        i2c_interrupt_flag_clear(i2cx->i2c_x, I2C_INT_FLAG_AERR);
        
        if(i2c_flag_get(i2cx->i2c_x,I2C_FLAG_MASTER)!=SET)
        {
            i2cx->i2c_control.Com_Flag.Bits.SendSucess = DRV_SUCCESS;
            i2cx->i2c_control.Com_Flag.Bits.SendState = 0;
            
            if(i2cx->i2c_slave_end_callback!=NULL)
            {
                i2cx->i2c_slave_end_callback(i2cx);        
            }        
        }else
        {
            if(i2cx->i2c_err_callback!=NULL)
            {
                i2cx->i2c_err_callback(i2cx);        
            }        
        }
    }
      
}
